syntax = "proto3";

package kuma.mesh.v1alpha1;

option go_package = "github.com/kumahq/kuma/api/mesh/v1alpha1";

import "api/mesh/options.proto";
import "api/mesh/v1alpha1/metrics.proto";
import "api/mesh/v1alpha1/envoy_admin.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";
import "validate/validate.proto";
import "kuma-doc/config.proto";

option (doc.config) = {
  type : Proxy,
  name : "Dataplane",
  file_name : "dataplane"
};

// Dataplane defines a configuration of a side-car proxy.
message Dataplane {

  option (kuma.mesh.resource).name = "DataplaneResource";
  option (kuma.mesh.resource).type = "Dataplane";
  option (kuma.mesh.resource).package = "mesh";
  option (kuma.mesh.resource).kds.send_to_global = true;
  option (kuma.mesh.resource).ws.name = "dataplane";
  option (kuma.mesh.resource).scope_namespace = true;
  option (kuma.mesh.resource).has_insights = true;
  option (kuma.mesh.resource).additional_printer_columns =
      "description=\"Service tag of the first "
      "inbound\",JSONPath=`.spec.networking.inbound[0].tags[\'kuma\\.io/"
      "service\']`,name=\"kuma.io/service\",type=string";
  option (kuma.mesh.resource).additional_printer_columns =
      "description=\"Service tag of the second "
      "inbound\",JSONPath=`.spec.networking.inbound[1].tags[\'kuma\\.io/"
      "service\']`,name=\"kuma.io/service\",type=string";
  option (kuma.mesh.resource).additional_printer_columns =
      "description=\"Service tag of the third "
      "inbound\",JSONPath=`.spec.networking.inbound[2].tags[\'kuma\\.io/"
      "service\']`,name=\"kuma.io/service\",type=string,priority=1";
  option (kuma.mesh.resource).additional_printer_columns =
      "description=\"Service tag of the fourth "
      "inbound\",JSONPath=`.spec.networking.inbound[3].tags[\'kuma\\.io/"
      "service\']`,name=\"kuma.io/service\",type=string,priority=1";

  // Networking describes inbound and outbound interfaces of a data plane proxy.
  message Networking {

    // IP on which the data plane proxy is accessible to the control plane and
    // other data plane proxies in the same network. This can also be a
    // hostname, in which case the control plane will periodically resolve it.
    string address = 5 [ (doc.required) = true ];

    reserved 6; // Formerly ingress mode message, see #3435

    // In some situations, a data plane proxy resides in a private network (e.g.
    // Docker) and is not reachable via `address` to other data plane proxies.
    // `advertisedAddress` is configured with a routable address for such data
    // plane proxy so that other proxies in the mesh can connect to it over
    // `advertisedAddress` and not via address.
    //
    // Envoy still binds to the `address`, not `advertisedAddress`.
    string advertisedAddress = 7;

    // Inbound describes a service implemented by the data plane proxy.
    // All incoming traffic to a data plane proxy are going through inbound
    // listeners. For every defined Inbound there is a corresponding Envoy
    // Listener.
    message Inbound {
      // Port of the inbound interface that will forward requests to the
      // service.
      //
      // When transparent proxying is used, it is a port on which the service is
      // listening to. When transparent proxying is not used, Envoy will bind to
      // this port.
      uint32 port = 3 [ (doc.required) = true ];

      // Port of the service that requests will be forwarded to.
      // Defaults to the same value as `port`.
      uint32 servicePort = 4;

      // Address of the service that requests will be forwarded to.
      // Defaults to 'inbound.address', since Kuma DP should be deployed next
      // to the service.
      string serviceAddress = 6;

      // Address on which inbound listener will be exposed.
      // Defaults to `networking.address`.
      string address = 5;

      // Tags associated with an application this data plane proxy is deployed
      // next to, e.g. `kuma.io/service=web`, `version=1.0`. You can then
      // reference these tags in policies like MeshTrafficPermission.
      // `kuma.io/service` tag is mandatory.
      map<string, string> tags = 2
          [ (validate.rules).map.min_pairs = 1, (doc.required) = true ];

      // Health describes the status of an inbound
      message Health {
        // Ready indicates if the data plane proxy is ready to serve the
        // traffic.
        bool ready = 1;
      }

      // Health describes the status of an inbound.
      // If 'health' is nil we consider data plane proxy as healthy.
      // Unhealthy data plane proxies are excluded from Endpoints Discovery
      // Service (EDS). On Kubernetes, it is filled automatically by the control
      // plane if Pod has readiness probe configured. On Universal, it can be
      // set by the external health checking system, but the most common way is
      // to use service probes.
      //
      // See https://kuma.io/docs/latest/documentation/health for more
      // information.
      Health health = 7;

      // ServiceProbe defines parameters for probing service's port
      message ServiceProbe {
        // Interval between consecutive health checks.
        google.protobuf.Duration interval = 1;

        // Maximum time to wait for a health check response.
        google.protobuf.Duration timeout = 2;

        // Number of consecutive unhealthy checks before considering a host
        // unhealthy.
        google.protobuf.UInt32Value unhealthy_threshold = 3;

        // Number of consecutive healthy checks before considering a host
        // healthy.
        google.protobuf.UInt32Value healthy_threshold = 4;

        message Tcp {}
        // Tcp checker tries to establish tcp connection with destination
        Tcp tcp = 5;
      }

      // ServiceProbe defines parameters for probing the service next to
      // sidecar. When service probe is defined, Envoy will periodically health
      // check the application next to it and report the status to the control
      // plane. On Kubernetes, Kuma deployments rely on Kubernetes probes so
      // this is not used.
      //
      // See https://kuma.io/docs/latest/documentation/health for more
      // information.
      ServiceProbe serviceProbe = 8;

      enum State {
        // Inbound is ready to serve the traffic.
        Ready = 0;
        // Inbound is not ready to serve the traffic.
        NotReady = 1;
        // Inbound is not created. It cannot be targeted by policies.
        // However, a data plane proxy receives a certificate with identity of
        // this inbound.
        Ignored = 2;
      }

      // State describes the current state of the listener.
      State state = 9;
    }

    // Outbound describes a service consumed by the data plane proxy.
    // For every defined Outbound there is a corresponding Envoy Listener.
    message Outbound {
      // IP on which the consumed service will be available to this data plane
      // proxy. On Kubernetes, it's usually ClusterIP of a Service or PodIP of a
      // Headless Service. Defaults to 127.0.0.1
      string address = 3;

      // Port on which the consumed service will be available to this data plane
      // proxy. When transparent proxying is not used, Envoy will bind to this
      // port.
      uint32 port = 4 [ (doc.required) = true ];

      // Tags of consumed data plane proxies.
      // `kuma.io/service` tag is required.
      // These tags can then be referenced in `destinations` section of policies
      // like TrafficRoute or in `to` section in policies like MeshAccessLog. It
      // is recommended to only use `kuma.io/service`. If you need to consume
      // specific data plane proxy of a service (for example: `version=v2`) the
      // better practice is to use TrafficRoute.
      map<string, string> tags = 5;
    }

    // Gateway describes a service that ingress should not be proxied.
    message Gateway {
      enum GatewayType {
        // A `DELEGATED` gateway is an independently deployed proxy that
        // receives inbound traffic that is not proxied by Kuma, and
        // it sends outbound traffic into the data plane proxy.
        DELEGATED = 0;
        // The `BUILTIN` gateway type configures data plane proxy itself as a
        // gateway.
        BUILTIN = 1;
      }

      // Tags associated with a gateway of this data plane to, e.g.
      // `kuma.io/service=gateway`, `env=prod`. `kuma.io/service` tag is
      // mandatory.
      map<string, string> tags = 1
          [ (validate.rules).map.min_pairs = 1, (doc.required) = true ];

      // Type of gateway this data plane proxy manages.
      // There are two types: `DELEGATED` and `BUILTIN`. Defaults to
      // `DELEGATED`.
      //
      // A `DELEGATED` gateway is an independently deployed proxy (e.g., Kong,
      // Contour, etc) that receives inbound traffic that is not proxied by
      // Kuma, and it sends outbound traffic into the data plane proxy.
      //
      // The `BUILTIN` gateway type causes the data plane proxy itself to be
      // configured as a gateway.
      //
      // See https://kuma.io/docs/latest/explore/gateway/ for more information.
      GatewayType type = 2 [ (doc.required) = true ];
    }

    // TransparentProxying describes configuration for transparent proxying.
    message TransparentProxying {

      // Port on which all inbound traffic is being transparently redirected.
      uint32 redirect_port_inbound = 1
          [ (validate.rules).uint32 = {lte : 65535} ];

      // Port on which all outbound traffic is being transparently redirected.
      uint32 redirect_port_outbound = 2
          [ (validate.rules).uint32 = {lte : 65535} ];

      // List of services that will be accessed directly via IP:PORT
      // Use `*` to indicate direct access to every service in the Mesh.
      // Using `*` to directly access every service is a resource-intensive
      // operation, use it only if needed.
      repeated string direct_access_services = 3;

      // Port on which all IPv6 inbound traffic is being transparently
      // redirected.
      uint32 redirect_port_inbound_v6 = 4
          [ (validate.rules).uint32 = {lte : 65535} ];

      // List of reachable services (represented by the value of
      // `kuma.io/service`) via transparent proxying. Setting an explicit list
      // can dramatically improve the performance of the mesh. If not specified,
      // all services in the mesh are reachable.
      repeated string reachable_services = 5;
    }

    // Gateway describes a configuration of the gateway of the data plane proxy.
    Gateway gateway = 3;

    // Inbound describes a list of inbound interfaces of the data plane proxy.
    //
    // Inbound describes a service implemented by the data plane proxy.
    // All incoming traffic to a data plane proxy is going through inbound
    // listeners. For every defined Inbound there is a corresponding Envoy
    // Listener.
    repeated Inbound inbound = 1;

    // Outbound describes a list of services consumed by the data plane proxy.
    // For every defined Outbound, there is a corresponding Envoy Listener.
    repeated Outbound outbound = 2;

    // TransparentProxying describes the configuration for transparent proxying.
    // It is used by default on Kubernetes.
    TransparentProxying transparent_proxying = 4;

    // Admin describes configuration related to Envoy Admin API.
    // Due to security, all the Envoy Admin endpoints are exposed only on
    // localhost. Additionally, Envoy will expose `/ready` endpoint on
    // `networking.address` for health checking systems to be able to check the
    // state of Envoy. The rest of the endpoints exposed on `networking.address`
    // are always protected by mTLS and only meant to be consumed internally by
    // the control plane.
    EnvoyAdmin admin = 8;
  }

  // Networking describes inbound and outbound interfaces of the data plane
  // proxy.
  Networking networking = 1;

  // Configuration for metrics that should be collected and exposed by the
  // data plane proxy.
  //
  // Settings defined here will override their respective defaults
  // defined at a Mesh level.
  MetricsBackend metrics = 2;

  message Probes {
    // Port on which the probe endpoints will be exposed. This cannot overlap
    // with any other ports.
    uint32 port = 1 [ (doc.required) = true ];

    message Endpoint {
      // Inbound port is a port of the application from which we expose the
      // endpoint.
      uint32 inbound_port = 1 [ (doc.required) = true ];
      // Inbound path is a path of the application from which we expose the
      // endpoint. It is recommended to be as specific as possible.
      string inbound_path = 2 [ (doc.required) = true ];
      // Path is a path on which we expose inbound path on the probes port.
      string path = 3 [ (doc.required) = true ];
    }

    // List of endpoints to expose without mTLS.
    repeated Endpoint endpoints = 2 [ (doc.required) = true ];
  }

  // Probes describe a list of endpoints that will be exposed without mTLS.
  // This is useful to expose the health endpoints of the application so the
  // orchestration system (e.g. Kubernetes) can still health check the
  // application.
  //
  // See
  // https://kuma.io/docs/latest/policies/service-health-probes/#virtual-probes
  // for more information.
  Probes probes = 3;
}
